import { computed, reactive, ref, Ref } from 'vue'
import { PopoverType } from '@/components/contract/useWidgetPopover'
import { Widget } from '@/models'
import { ImageData, Viewer } from '@/types'

/** 图片上传 */
export default function useUpload({
  data,
  viewer
}: {
  /** 控件数据 */
  data: Ref<Widget>

  /** 文档查看 组件实例 */
  viewer: Ref<Viewer>
}) {
  /** 文件上传 input */
  const input = ref(null as HTMLInputElement | null)

  /** 加载中 */
  const loading = computed({
    set: (val: boolean) => (data.value.image.loading = val),
    get: () => data.value.image.loading
  })

  /** 处理文件 */
  async function handler(files: FileList) {
    const widget = data.value
    const [file] = Array.from(files)
    const { imageCrop } = viewer.value

    if (imageCrop) {
      widget.extra.file = file
      viewer.value.$emit('popover-open', PopoverType.IMAGE_CROP, null, widget, (file: File) => handlerUpload(file))
    } else {
      handlerUpload(file)
    }
  }

  /** 处理文件上传 */
  async function handlerUpload(file: File) {
    const widget = data.value
    const { imageUpload: upload, imageSrc } = viewer.value

    if (!upload) throw '请提供 `imageUpload` 方法以上传附件'

    loading.value = true

    try {
      const { id, name, src } = await upload(file, widget)

      widget.value = id

      Object.assign(widget.image, {
        name: name || file.name,
        src: src && !imageSrc ? src : ''
      } as Partial<ImageData>)
    } finally {
      loading.value = false
      widget.extra.file = null
    }
  }

  return reactive({
    input,

    /** 附件接受上传的文件类型 */
    accept: computed(() => data.value.image.accept || viewer.value.imageAccept || ''),

    /** 加载中 */
    loading,

    /** 图片 */
    image: computed(() => {
      const widget = data.value

      return widget.image.src || (widget.value ? viewer.value.imageSrc?.(widget) : '') || ''
    }),

    /** 区域点击上传 */
    areaClick() {
      const ipt = input.value
      if (ipt) {
        ipt.value = ''
        ipt.click()
      }
    },

    /** 文件更改 */
    fileChange(e: Event) {
      handler((e.target as HTMLInputElement).files as FileList)
    },

    /** 文件拖拽 */
    fileDrop(e: DragEvent) {
      handler(e.dataTransfer?.files as FileList)
    }
  })
}
